package cn.example.vip.mall.api.permission;

import cn.example.vip.mall.api.util.IpUtil;
import cn.example.vip.mall.permission.entity.Permission;
import cn.example.vip.mall.util.JwtToken;
import cn.example.vip.mall.util.MD5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 权限验证
 */
@Component
public class AuthVerifyInterceptor {
	
	@Autowired
	private RedisTemplate redisTemplate;
	
	/**
	 * 用户验证 JWT
	 * @param token
	 * @param clientIp
	 * @return
	 */
	public static Map<String, Object> JwtVerify(String token, String clientIp) {
		// 解析Token
		Map<String, Object> result = JwtToken.parseToken(token);
		// 比较MD5.md5(ip)
		try {
			if(MD5.md5(clientIp).equals(result.get("ip").toString())){
				return result;
			}
		} catch (Exception e) {
//			throw new RuntimeException(e);
			e.printStackTrace();
		}
		return null;
	}
	
	public static void test_main(String[] args) {
		AntPathMatcher antPathMatcher = new AntPathMatcher();
		System.out.println("AntPathMatcher,匹配测试!!!");
		System.out.println("all:" + antPathMatcher.match("/path/a/b", "/path/a/b"));											// all:true
		System.out.println("all:" + antPathMatcher.match("/path/{String}/{Integer}", "/path/str/1"));							// all:true
		System.out.println("all:" + antPathMatcher.match("/path/{String}/{Integer}", "/path/str/"));							// all:false
		System.out.println("all:" + antPathMatcher.match("/path/{String}/{Integer}", "/path/str"));							// all:false
		System.out.println("all:" + antPathMatcher.extractUriTemplateVariables("/path/{String}/{Integer}", "/path/str/1"));	// all:{String=str, Integer=1}
		System.out.println("all:" + antPathMatcher.match("/path/*/*", "/path/a/b"));											// all:true
		
	}
	
	/**
	 * 根据 shop_permission 数据库的 url_match 判断是否需要拦截
	 * @return isInterceptor?
	 */
	public Boolean isInterceptor(ServerWebExchange exchange) {
		ServerHttpRequest serverHttpRequest = exchange.getRequest();
		// 从当前请求获取 URI
		String uri = serverHttpRequest.getURI().getPath();
		// 当前请求的请求方式 GET POST PUT DELETE
		String method = serverHttpRequest.getMethodValue();
		// 从软件网关交换机的请求参数上获取服务名称 service-name
		URI routeUri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
		System.out.println("-----routeUri:" + routeUri);
		String serviceName = routeUri.getHost();
		System.out.println("-----serviceName:" + serviceName);
		// 从 Redis 中查找并匹配:0.完全匹配,1.通配符匹配
		List<Permission> permissionMatch0 = (List<Permission>) redisTemplate.boundHashOps("RolePermissionAll").get("PermissionMatch0");
		List<Permission> permissionMatch1 = (List<Permission>) redisTemplate.boundHashOps("RolePermissionAll").get("PermissionMatch1");
		Permission permission = null;
		// 0
		if(permissionMatch0 != null){
			permission = match0(permissionMatch0, uri, method, serviceName);	// 获取匹配结果
		}
		// 1
		
		// permission == null 则进行通配符匹配
		if(permission == null){
			// 通配符匹配
			
			// 如果不匹配则默认放行
			return false;
		}

		return true;
	}
	
	/**
	 * 令牌校验拦截器
	 * @param exchange
	 * @return
	 */
	public Map<String, Object> tokenInterceptor(ServerWebExchange exchange) {
		ServerHttpRequest request = exchange.getRequest();
		// 其他地址则进行校验
		String clientIp = IpUtil.getIp(request);
		// 获取令牌信息
		String token = request.getHeaders().getFirst("Authorization");
		// 令牌校验
		Map<String, Object> jwtMap = AuthVerifyInterceptor.JwtVerify(token, clientIp);
		return jwtMap;
	}
	
	public Boolean rolePermission(ServerWebExchange exchange, Map<String, Object> tokenMap) {
		// 1.权限校验:uri,method,serviceName
		ServerHttpRequest serverHttpRequest = exchange.getRequest();
		// 从当前请求获取 URI
		String uri = serverHttpRequest.getURI().getPath();
		// 当前请求的请求方式 GET POST PUT DELETE
		String method = serverHttpRequest.getMethodValue();
		// 从软件网关交换机的请求参数上获取服务名称 service-name
		URI routeUri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
		String serviceName = routeUri.getHost();
		// 2.执行匹配,获取角色集合
		String[] roles = tokenMap.get("roles").toString().split(",");
		// 3.循环判断角色是否有权限,完全匹配
		Permission permission = null;
		for(String role : roles) {
			// 向 Redis 查询角色
			Set<Permission> permissions = (Set<Permission>) redisTemplate.boundHashOps("RolePermissionMap").get("Role_0_" + role);
			// obj.stream().map(Permission.class::cast).collect(Collectors.toList());
//			permissions = Arrays.asList(obj);
			if(permissions == null){
				continue;
			}
			// 完全匹配
			permission = match0(new ArrayList<Permission>(permissions), uri, method, serviceName);
			if (permission != null) {
				System.out.println("match0");
				break;
			}
			// 参数匹配
			permission = match1(new ArrayList<Permission>(permissions), uri, method, serviceName);
			if (permission != null) {
				System.out.println("match1");
				break;
			}
		}
		
		//
		if(permission == null){
		
		}
		return permission != null;
	}
	
	/**
	 * 完全匹配路径,鉴权
	 * @param permissionMatch0
	 * @param uri
	 * @param method
	 * @param serviceName
	 * @return
	 */
	public Permission match0(List<Permission> permissionMatch0, String uri, String method, String serviceName) {
		for(Permission permission : permissionMatch0){
			// 匹配
			String matchUrl = permission.getUrl();
			String matchMethod = permission.getMethod();
			String matchServiceName = permission.getServiceName();
			// 1.uri
			if(matchUrl.equals(uri)){
				// 1.1.提交方式和服务匹配
				if(method.equals(matchMethod) && serviceName.equals(matchServiceName)) {
					return permission;
				}
				// 1.2.匹配方法的通配符
				if ("*".equals(matchUrl)) {
					return permission;
				}
			}
		}
		return null;
	}
	
	/**
	 * 参数匹配路径,鉴权
	 * @param permissionMatch1
	 * @param uri
	 * @param method
	 * @param serviceName
	 * @return
	 */
	public Permission match1(List<Permission> permissionMatch1, String uri, String method, String serviceName) {
		for(Permission permission : permissionMatch1){
			// 匹配
			String matchUrl = permission.getUrl();
			String matchMethod = permission.getMethod();
			String matchServiceName = permission.getServiceName();
			// AntPathMatcher 匹配参数
			AntPathMatcher antPathMatcher = new AntPathMatcher();
			// 1.uri
			if(antPathMatcher.match(matchUrl, uri)){
				// antPathMatcher.extractUriTemplateVariables("/path/{String}/{Integer}", "/path/str/1"));	// all:{String=str, Integer=1}
				// 1.1.提交方式和服务匹配
				if(method.equals(matchMethod) && serviceName.equals(matchServiceName)) {
					return permission;
				}
				// 1.2.匹配方法的通配符
				if("*".equals(matchUrl)){
					return permission;
				}
			}
		}
		return null;
	}
}
